In a computing apparatus in which memory is used to store data, the memory is typically divided into a number of portions allocated to programs executed on the computing apparatus to store data for the programs. Each allocated portion of the memory is freed for reuse when it is no longer needed by a respective program to which the portion of memory is allocated. There are, however, several issues associated with existing approaches to buffer allocation and management. For example, the allocation size of each portion of the memory is usually pre-specified and may, at times, be larger than what is needed. The efficiency of buffer allocation under existing approaches also tend to be less than optimal at times, as it is possible for a program needing a portion of memory yet not having any portion of the buffer allocated for it. In some cases, there is long latency and low throughput in accessing the memory.